package cn.springBoot.util;

import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.collections4.MapUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.amazonaws.services.directory.model.ServiceException;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.IOUtils;

/**
 * <p>
 * spring 转化成pdf 上传到七牛云
 * </p>
 *
 * @author ljx
 * @class com.hlwl.task.util.PdfUploadUtil
 * @create date: 2021/12/14
 */
public class PdfUploadUtil {
    private static final Logger logger = LoggerFactory.getLogger(PdfUploadUtil.class.getName());

    private static final String URL = "http://platformfiles.hlwl.com/";

    private static final String accessKey = "QJImoahsJdiau0I1QJ008N43JwOt5dzx9vjHTM-j";

    private static final String secretKey = "AdIeSo3NBj0w11gtuKS4G8R6YV-FgWnvE0QCYCzP";

    private static final String bucket = "hlwlmiddleground";

    private static DefaultPutRet putRet = null;
    private static Response response = null;
    private static Object putRetRespons = null;

    public static String uploadPdf(String savePath, String text) {

        try {
            // String savePath = request.getServletContext().getRealPath("/tmp");
            // 新建document对象
            Document document = new Document();
            // 左，右，上，下
            document.setMargins(30, 30, 40, 40);
            File file = new File(savePath);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
            // 3.打开文档
            document.open();
            // 这里是必须要设置编码的，不然导出中文就会乱码。
            byte[] b = text.getBytes("utf-8");
            // 将字节数组包装到流中
            ByteArrayInputStream bis = new ByteArrayInputStream(b);
            XMLWorkerHelper.getInstance().parseXHtml(writer, document, bis, Charset.forName("UTF-8"));
            // 5.关闭文档
            document.close();
            bis.close();
            // 将字节数组包装到流中
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int len = 0;
            // 将内容读到buffer中，读到末尾为-1
            while ((len = fis.read(buffer)) != -1) {

                outStream.write(buffer, 0, len);
            }
            Map<String, Object> pdfResultMap = uploadFile(outStream, "contract.pdf");
            String url = MapUtils.getString(pdfResultMap, "url");
            fis.close();
            outStream.close();
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new ServiceException("文件上传到云服务器失败");
    }

    public static String uploadWord(String saveTempPath, String text) {

        try {

            System.out.println("生成的word文档地址" + saveTempPath);

            // 这里是必须要设置编码的，不然导出中文就会乱码。
            byte[] b = text.getBytes("utf-8");
            // 将字节数组包装到流中
            ByteArrayInputStream bais = new ByteArrayInputStream(b);

            // 创建 POIFSFileSystem 对象
            POIFSFileSystem poifs = new POIFSFileSystem();
            // 获取DirectoryEntry
            DirectoryEntry directory = poifs.getRoot();

            OutputStream out = new FileOutputStream(saveTempPath);
            // 创建文档,1.格式,2.HTML文件输入流
            directory.createDocument("WordDocument", bais);
            // 写入
            poifs.writeFilesystem(out);
            // 释放资源
            out.close();
            bais.close();
            poifs.close();
            System.out.println("success");

            FileInputStream fis = new FileInputStream(saveTempPath);
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int len = 0;
            // 将内容读到buffer中，读到末尾为-1
            while ((len = fis.read(buffer)) != -1) {

                outStream.write(buffer, 0, len);
            }
            Map<String, Object> pdfResultMap = uploadFile(outStream, ".doc");
            String url = MapUtils.getString(pdfResultMap, "url");
            fis.close();
            outStream.close();

            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new ServiceException("文件上传到云服务器失败");
    }

    /**
     * <p>
     * Description:订单pdf文件转img文件
     * </p>
     * 
     * @param pdfPath
     */
    public static String pdfToImg(String pdfPath, String imgPath) {
        File file = new File(pdfPath);
        PDDocument pdDocument;
        try {

            pdDocument = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            /* 第二位参数越大转换后越清晰，相对转换速度越慢 */
            BufferedImage image = renderer.renderImageWithDPI(0, 100);
            ImageIO.write(image, "png", new File(imgPath));
            pdDocument.close();

            FileInputStream fis = new FileInputStream(imgPath);
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int len = 0;
            // 将内容读到buffer中，读到末尾为-1
            while ((len = fis.read(buffer)) != -1) {

                outStream.write(buffer, 0, len);
            }
            Map<String, Object> pdfResultMap = uploadFile(outStream, ".png");
            String url = MapUtils.getString(pdfResultMap, "url");
            fis.close();
            outStream.close();

            return url;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private static Object upload(byte[] uploadBytes, String fileName) {
        logger.info("【开始】QNFileUpload::upload，fileName={}", fileName);

        // 密钥配置
        Auth auth = Auth.create(accessKey, secretKey);
        // 指定上传的Zone
        Configuration cfg = new Configuration(CustomRegion.regionHD());
        // 创建上传对象
        UploadManager uploadManager = new UploadManager(cfg);
        // 简单上传，使用默认策略，仅设置上传的空间
        String upToken = auth.uploadToken(bucket);

        try {
            // 调用put方法上传
            logger.info("【开始】QNFileUpload::upload::uploadManager.put，upToken={}", upToken);
            Response response = uploadManager.put(uploadBytes, setName(fileName), upToken);
            logger.info("【结束】QNFileUpload::upload::uploadManager.put");
            // 封装返回信息对象
            putRetRespons = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
        } catch (QiniuException ex) {
            ex.printStackTrace();
            logger.error("【结束】QNFileUpload::upload::uploadManager.put，上传报异常，\nMessage={}，\nerror={}", ex.getMessage(),
                ex.error());
            logger.error("\n**************" + JSON.toJSONString(ex));
            putRetRespons = ex.response;
        }

        logger.info("\n\n【结束】QNFileUpload::upload，fileName={}", fileName);
        return putRetRespons;
    }

    private static Map<String, Object> base64Upload(String base64Str, String name) {
        byte[] base64Strz = Base64.getDecoder().decode(base64Str);
        return returnInfo(upload(base64Strz, name), name);
    }

    /**
     * 异常类的处理
     *
     * @param isKey
     * @return
     */
    private static Map<String, Object> returnInfo(Object isKey, String name) {
        Map<String, Object> r = new HashMap<String, Object>();
        if (isKey instanceof DefaultPutRet) {
            putRet = (DefaultPutRet)isKey;
            r.put("code", 200);
            r.put("name", name);
            r.put("url", URL + putRet.key);
            r.put("data", URL + putRet.key);
            r.put("total", 0);
            r.put("msg", "");
        } else {
            response = (Response)isKey;
            r.put("code", 400);
            r.put("data", response.error);
            r.put("msg", response.error);
            r.put("total", 0);
        }
        return r;

    }

    private static String setName(String name) {
        StringBuffer sb = new StringBuffer();
        // 设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String date = df.format(new Date());
        sb.append(date).append(name);
        return sb.toString();
    }

    /**
     * 上传文件到七牛云
     *
     * @param data
     *            文件字节数据
     * @param originalFilename
     *            原始文件名
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @author zhuhh
     * @date 2020/2/3 2:30 下午
     */
    private static Map<String, Object> uploadFile(byte[] data, String originalFilename) {
        return returnInfo(upload(data, originalFilename), originalFilename);
    }

    /**
     * 通过流上传文件到七牛云
     *
     * @param outputStream
     *            输出流
     * @param fileName
     *            文件名称
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @author zhuhh
     * @date 2021/2/3
     */
    private static Map<String, Object> uploadFile(ByteArrayOutputStream outputStream, String fileName) {
        byte[] bytes = outputStream.toByteArray();
        return uploadFile(bytes, fileName);
    }

    /**
     * 根据文件名上传阿里云
     *
     * @param outputFileName
     *            文件名称
     *
     * @return map
     *
     * @author zhuhh create date 2021/6/19
     */
    private Map<String, Object> upload(final String outputFileName) {
        byte[] bytes;
        try {
            bytes = IOUtils.toByteArray(new FileInputStream(outputFileName));
            Map<String, Object> uploadResultMap = uploadFile(bytes, outputFileName);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("fileName", uploadResultMap.get("name"));
            resultMap.put("fileUrl", uploadResultMap.get("url"));

            return resultMap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        throw new ServiceException("文件上传到云服务器失败");
    }
}
